<script setup lang="ts">
import { Close } from '@element-plus/icons-vue'
import { omit } from 'lodash-es'
import IndicatorBasis from './IndicatorBasis.vue'
import IndicatorExpression from './IndicatorExpression.vue'
import IndicatorDataStorage from './IndicatorDataStorage.vue'
import { useStatisticalIndicators } from '@/mixins/StatisticalIndicators/MixinStatisticalIndicators'

import type { CustomDialogInstance } from '@/types/modules/public'
import type { StatisticalIndicator } from '@/types/modules/statistical-indicator'
import type { Point } from '@/components/ReadonlyPointTree/ReadonlyPointTree'

const props = defineProps<{
  indicatorId: number
  point: Point
  modalTitle?: string
  isAdd: boolean
}>()

const emits = defineEmits<{
  (e: 'save-success'): void
}>()
const defaults: StatisticalIndicator = {
  id: 0,
  pointCode: '',
  pointId: 0,
  pointName: '',
  indicatorCode: '',
  indicatorName: '',
  indicatorNumber: '',
  unitId: 0,
  unitName: '',
  unitExpression: '',
  expressionType: [],
  calculationalExpression: '',
  calculationalExpressionStatus: 0,
  statisticalExpression: '',
  statisticalExpressionStatus: 0,
  storageMode: {
    collect: [],
    entry: [],
    calculate: [],
    statistic: [],
  },
}
const dialogRef = ref<CustomDialogInstance>()

const [indicator, setIndicator]
  = useState<StatisticalIndicator>({
    ...defaults,
    id: unref(props.indicatorId),
    pointId: unref(props.point).id,
    pointName: unref(props.point).pointName,
    pointCode: unref(props.point).pointCode ?? '',
  })
const [currentStep, setCurrentStep] = useState(0)
const [saving, setSaving] = useState(false)
const currentStepComponent = computed(() => {
  switch (currentStep.value) {
    case 0:
      return IndicatorBasis
    case 1:
      return IndicatorExpression
    case 2:
      return IndicatorDataStorage
    default:
      return null
  }
})
const stepComponentRef = ref<typeof currentStepComponent>()
const cancelButtonText = computed(() => {
  if (currentStep.value === 0) {
    return '关闭'
  }
  else {
    return '上一步'
  }
})
const confirmButtonText = computed(() => {
  if (currentStep.value === 2) {
    return '保存并关闭'
  }
  else {
    return '保存至下一步'
  }
})

const {
  getIndicatorDetailsById,
  saveOrUpdateOneStep,
  saveOrUpdateTwoStep,
  saveOrUpdateThreeStep,
} = useStatisticalIndicators()

// 暂存旧采集点点位
const [oldIndicatorCode, setOldIndicatorCode]
  = useState('')
// 暂存公式类型
const [oldExpressionType, setOldExpressionType] = useState<
  any[]
>([])

function clickCancelButton() {
  if (unref(currentStep) === 0) {
    close()
    return
  }
  setCurrentStep((unref(currentStep) - 1) % 3)
}
async function clickConfirmButton() {
  if ((unref(stepComponentRef) as any).validate) {
    const isValid = await (unref(stepComponentRef) as any)
      .validate()
      .catch(() => {})
    if (!isValid)
      return
  }

  const t = unref(currentStep)
  setSaving(true)
  // 保存当前
  if (t === 0) {
    // 第一步
    try {
      const data = await saveOrUpdateOneStep(
        unref(indicator),
      )
      setSaving(false)
      if (data.id) {
        // 基本信息保存成功后，如果把”采集点点位“删除后
        // 给出更新数据存储方式的提示
        const tt = unref(indicator)
        const hasCanceled
          = tt.storageMode.collect.length > 0
          && unref(oldIndicatorCode) !== ''
          && tt.indicatorCode === ''
        if (hasCanceled) {
          ElMessage.warning(
            '采集点点位已删除，请更新对应的数据存储方式',
          )
        }
        else {
          ElMessage.success('保存成功')
        }
        setIndicator({
          ...unref(indicator),
          id: data.id,
        })
      }
      else {
        return
      }
    }
    catch (e) {}
  }
  else if (t === 1) {
    // 第二步
    const expressionType = unref(indicator).expressionType
    // 没有勾选“计算公式"，则清空公式表达式内容
    if (!expressionType.includes(1)) {
      indicator.value.calculationalExpression = ''
      indicator.value.calculationalExpressionStatus = 0
    }
    // 没有勾选“统计公式"，则清空统计公式表达式内容
    if (!expressionType.includes(2)) {
      indicator.value.statisticalExpression = ''
      indicator.value.statisticalExpressionStatus = 0
    }
    await nextTick()
    const state = await saveOrUpdateTwoStep(
      unref(indicator),
    )
    setSaving(false)
    if (!state)
      return
    // 保存成功后如果取消了公式，给出提示去更新对应的数据存储
    // 以免造成取消了公式却还有公式的数据存储方式
    const tt = unref(indicator)
    const hasCanceled
      = (tt.storageMode.calculate.length > 0
      && tt.expressionType.includes(1) === false
      && unref(oldExpressionType).includes(1))
      || (tt.storageMode.statistic.length > 0
      && tt.expressionType.includes(2) === false
      && unref(oldExpressionType).includes(2))
    if (hasCanceled) {
      ElMessage.warning(
        '取消了公式，请更新对应的数据存储方式',
      )
    }
    else {
      ElMessage.success('保存成功')
    }
  }
  else if (t === 2) {
    // 第三步
    const state = await saveOrUpdateThreeStep(
      unref(indicator),
    )
    setSaving(false)
    if (!state)
      return
    ElMessage.success('保存成功')
  }
  if (unref(currentStep) < 2) {
    setCurrentStep((unref(currentStep) + 1) % 3)
  }
  else {
    close()
    // 三步都保存成功
    emits('save-success')
  }
}

// 更新统计指标时候初始化指标
async function updateIndicator() {
  // 新增统计指标
  if (unref(props.indicatorId) === 0) {
    // 新增时，清空暂存
    setOldIndicatorCode('')
    setOldExpressionType([])
    setIndicator({
      // fix: 解决storageMode因引用类型被IndicatorDataStorage组件中修改的问题
      ...omit(defaults, ['storageMode']),
      storageMode: {
        collect: [],
        entry: [],
        calculate: [],
        statistic: [],
      },
      pointId: unref(props.point).id,
      pointName: unref(props.point).pointFullName,
      pointCode: unref(props.point).pointCode ?? '',
      indicatorNumber: `${
        unref(props.point).pointCode ?? ''
      }.`,
    })
  }
  else {
    const details = await getIndicatorDetailsById(
      unref(props.indicatorId),
    )
    setOldIndicatorCode(details?.indicatorCode ?? '')
    setOldExpressionType(details?.expressionType ?? [])
    setIndicator({
      // fix: 解决storageMode因引用类型被IndicatorDataStorage组件中修改的问题
      ...omit(defaults, ['storageMode']),
      storageMode: {
        collect: [],
        entry: [],
        calculate: [],
        statistic: [],
      },
      ...details,
    })
  }
}

async function open() {
  setCurrentStep(0)
  updateIndicator()
  await nextTick()
  dialogRef.value?.open()
}
function close() {
  dialogRef.value?.close()
}

defineExpose({
  open,
  close,
})
</script>

<template>
  <CustomDialog
    ref="dialogRef"
    class="indicator-steps-dialog"
    title="统计指标信息"
    :no-max-height="true"
    :cancel-button-text="cancelButtonText"
    :confirm-button-text="confirmButtonText"
    width="60%"
  >
    <template #header="{ titleId, titleClass }">
      <div
        class="align-center flex justify-between"
        style="margin-top: 5px"
      >
        <span
          :id="titleId"
          :class="titleClass"
          style="margin: 0"
        >
          统计指标信息
        </span>
        <ElSteps
          :active="currentStep"
          simple
          finish-status="process"
          :space="200"
          style="width: 580px"
        >
          <ElStep title="基本信息" />
          <ElStep title="计算公式" />
          <ElStep title="数据存储" />
        </ElSteps>
        <div class="align-center flex">
          <ElIcon
            class="margin-left-sm c-pointer padding-xs box-content"
            @click="close"
          >
            <Close />
          </ElIcon>
        </div>
      </div>
    </template>
    <div class="step-content" style="user-select: text">
      <Transition
        enter-active-class="animate__animated animate__fadeIn"
      >
        <component
          :is="currentStepComponent"
          ref="stepComponentRef"
          v-model="indicator"
          :is-add="isAdd"
        />
      </Transition>
    </div>
    <template #footer>
      <span class="dialog-footer">
        <ElButton @click="clickCancelButton">
          {{ cancelButtonText }}
        </ElButton>
        <ElButton
          type="primary"
          :loading="saving"
          @click="clickConfirmButton"
        >
          {{ confirmButtonText }}
        </ElButton>
      </span>
    </template>
  </CustomDialog>
</template>

<style>
.indicator-steps-dialog {
  min-width: 850px;
  max-width: 1000px;
}
</style>

<style lang="scss" scoped>
.step-content {
  min-height: 440px;
  max-height: 550px;
  @include roll();
}
</style>
